/* 头文件声明区 */
#include <regx52.h>
#include "key.h"
#include "seg.h"

/* 变量声明区 */
typedef unsigned char u8;
typedef unsigned short u16;
//数码管相关变量
u8 Seg_buf[] = {10,10,10,10,10,10};//数码管显示内容数组
u8 Seg_pos = 0;//数码管扫描变量
u16 Seg_slow = 0;//数码管刷新速度
u8 U_collect[4] = {11,11,11,11};//电压采集变量数组千、百、十、个位（mv）
u8 Seg_disp_mode = 0;//数码管显示模式 
u8 U_collect_index = 0;
u8 star_flag;//闪烁标志位
u8 U_real[3] = {0};
u8 Seg_point[6] = {0,0,0,0,0,0};
float U_set = 3.0; 
int Count;//计数变量
//u8 flag = 0;//
u8 Count_flag = 0;


//按键相关变量
u8 Key_val,Key_old,Key_down;//按键处理变量
u8 Key_slow;//数码管减速变量

//led相关变量
u8 led_flag = 0;//led1标志位
u8 led3_shine_flag = 0;//led3亮的标志位
u8 err_count = 0;//无效按键操作计数
//计时变量
u8 timer_250ms = 0;//计时250ms
u16 timer_conut_5000ms = 0;//计时5000ms
/* 按键信息处理函数 */
void Key_proces()
{
	u8 i  = 0;
	if(Key_slow)return;
	Key_slow = 1;
	
	Key_val = Key_read();
	Key_down = Key_val & (Key_val ^ Key_old);
	Key_old = Key_val;
	
	if(Key_down >= 1 && Key_down <= 10)//只在采集界面生效的
	{	
		if(Seg_disp_mode == 0 && U_collect_index < 4)
		{
			err_count = 0;//正确操作后清零
			led3_shine_flag = 0;//led3标志位熄灭
			U_collect[U_collect_index] = Key_down - 1;
			U_collect_index++;
		}
		else//如果不是在采集模式下按，记错
		{
			err_count++;
			if(err_count == 3)
			{
				led3_shine_flag = 1;
			}
		}
	}
	switch(Key_down)
	{
		case 11:
		{
			err_count = 0;//正确操作后清零
			led3_shine_flag = 0;//led3标志位熄灭
			if(Seg_disp_mode == 0)//在电压采集界面按下
			{
				
				if(U_collect_index >= 4)
				{
					for(i = 0;i < 3;i++)
					{
						U_real[i] = U_collect[i];//保存电压采集数据  
					}
					Seg_disp_mode = 1;//跳转电压显示界面
				}
				else
				{
					U_collect_index = 0;//复位
					for(i = 0;i < 4;i++)
					{
						U_collect[i] = 11;
					}
				}			
			}
			else//从其他界面回到采集界面也要复位
			{
				Seg_disp_mode = 0;
				U_collect_index = 0;//复位
				for(i = 0;i < 4;i++)
				{
					U_collect[i] = 11;				
				}
			}
			break;
		}
		case 14:
		{
			if(Seg_disp_mode == 0)//在电压采集界面按下
			{
				err_count = 0;//正确操作后清零
				led3_shine_flag = 0;//led3标志位熄灭
				for(i = 0;i < 4;i++)
				{
					U_collect[i] = 11;
					U_collect_index = 0;//将指针归零
				}
			}
			else if(Seg_disp_mode == 3)//在计数界面按下
			{
				err_count = 0;//正确操作后清零
				led3_shine_flag = 0;//led3标志位熄灭
				Count = 0;
			}
			else
			{
				err_count++;
				if(err_count == 3)
				{
					led3_shine_flag = 1;
				}
			}
			break;
		}
		case 12:
		{
			if(Seg_disp_mode != 0)
			{
				err_count = 0;//正确操作后清零
				led3_shine_flag = 0;//led3标志位熄灭
				if(++Seg_disp_mode == 4)Seg_disp_mode = 1;
			}
			else
			{
				err_count++;
				if(err_count == 3)
				{
					led3_shine_flag = 1;
				}
			}
			break;
		}
		case 15:
		{
			if(Seg_disp_mode == 2)
			{
				err_count = 0;//正确操作后清零
				led3_shine_flag = 0;//led3标志位熄灭
				U_set += 0.5;
				if(U_set > 6.0)U_set = 1.0;
			}
			else
			{
				err_count++;
				if(err_count == 3)
				{
					led3_shine_flag = 1;
				}
			}
			break;
		}
		case 16:
		{
			if(Seg_disp_mode == 2)
			{
				err_count = 0;//正确操作后清零
				led3_shine_flag = 0;//led3标志位熄灭
				U_set -= 0.5;
				if(U_set < 1.0)U_set = 6.0;
			}
			else
			{
				err_count++;
				if(err_count == 3)
				{
					led3_shine_flag = 1;
				}
			}
			break;
		}
		case 13:
		{
			err_count++;
			if(err_count == 3)
			{
				led3_shine_flag = 1;
			}
			break;
		}
	}	
}

/* 数码管信息处理函数 */
void Seg_proces()
{
	u8 i = 0;//循环变量
	if(Seg_slow)return;
	Seg_slow = 1;
	
	if((U_real[0]*1000 + U_real[1]* 100 + U_real[2] * 10) >  U_set * 1000)//如果实际电压超过参考电压，则让计数变量加一的标志位置1
		Count_flag = 1;
	else if(Count_flag == 1)//如果前面的if任然满足，则不会进入我们的Count++，巧妙地解决了前一次与后一次电压变化的判断
	{
		Count_flag = 0;
		Count ++;
	}
	switch(Seg_disp_mode)
	{
		case 0:
		{
			Seg_point[3] = 0;
			Seg_buf[0] = Seg_buf[1] = 10;//前两位熄灭			
			for(i = 0;i < 4;i++)
			{
				Seg_buf[i+2] = U_collect[i];
			}
			if(Seg_buf[5] == 11)
			{
				Seg_buf[2+U_collect_index] = star_flag ? U_collect[U_collect_index] : 10;
			}
			break;
		}
		case 1:
		{
			Seg_buf[0] = 12;//提示符U
			Seg_buf[1] = Seg_buf[2] = 10;//熄灭
			Seg_buf[3] = U_real[0];
			Seg_buf[4] = U_real[1];
			Seg_buf[5] = U_real[2];
			Seg_point[3] = 1;			
			break;
		}
		case 2:
		{
			Seg_buf[0] = 13;
			Seg_buf[1] = Seg_buf[2] = 10;//熄灭
			Seg_point[3] = 1;
			Seg_buf[3] = (u8)U_set % 10;//取个位
			Seg_buf[4] = (u8)((u8)(U_set*10) %10);
			Seg_buf[5] = 0;
			break;
		}
		case 3:
		{
			Seg_point[3] = 0;
			Seg_buf[0] = 14;
			Seg_buf[1] = Count / 10000 % 10;//取万位
			Seg_buf[2] = Count / 1000 % 10 ; //取千位
			Seg_buf[3] = Count / 100 % 10;//取百位
			Seg_buf[4] = Count / 10 % 10;//取十位
			Seg_buf[5] = Count % 10;//取个位
			for(i = 0;i < 5;i++)
			{
				if(Seg_buf[i] == 0)Seg_buf[i] = 10;
				else break;
			}       
			break;
		}
	}
}

void led_proces()
{
	//led1亮的条件
	if(led_flag)
		P1 &= 0xfe;
	else 
		P1 |= 0x01;
	//led2亮的条件
	if(Count%2 == 1)
		P1 &= 0xfd;
	else
		P1 |= 0x02;
	//led3亮的条件
	if(led3_shine_flag)
		P1 &= 0xfb;
	else
		P1 |= 0x04;
	
}
/* 定时器0中断初始化 */
void Timer0Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
/* 定时器0中断服务函数 */
void timer0server() interrupt 1
{
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if(++Seg_slow == 250)Seg_slow = 0;
	if(++Key_slow == 10)Key_slow = 0;
	if(++Seg_pos == 6)Seg_pos = 0;
	if(++timer_250ms == 250)
	{
		timer_250ms = 0;
		star_flag ^= 1;		
	}
	if((U_real[0]*1000 + U_real[1]* 100 + U_real[2] * 10) > U_set * 1000)
	{
		if(++timer_conut_5000ms == 5000)
		{
			led_flag = 1;//5s标志位		
		}
	}
	else
	{
		led_flag = 0;//5s标志位
		timer_conut_5000ms = 0;
	}

	Seg_disp(Seg_pos,Seg_buf[Seg_pos],Seg_point[Seg_pos]);
}
/* main函数 */
void main()
{
	Timer0Init();
	while(1)
	{
		Key_proces();
		Seg_proces();
		led_proces();
	}
}